/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef SPINLOCK_H
#define SPINLOCK_H

#include <plat/config.h>
#include <core/atomic.h>
#include <core/dprintf.h>

typedef struct sp_spinlock_t {
    atomic_t data;
} spinlock_t;

#define SPINLOCK_INIT_LOCKED \
    {                        \
        .data = { 1 }        \
    }
#define SPINLOCK_INIT_UNLOCKED \
    {                          \
        .data = { 0 }          \
    }

static inline int spin_is_locked(spinlock_t *lock)
{
    return atomic_load(&lock->data) == 1;
}

static inline void spin_init_unlocked(spinlock_t *lock)
{
    atomic_store(&lock->data, 0);
}

static inline void spin_init_locked(spinlock_t *lock)
{
    atomic_store(&lock->data, 1);
}

static inline int spin_try_lock(spinlock_t *lock)
{
    return (atomic_compare_exchange(&lock->data, 0, 1) == 0);
}

static inline void spin_lock(spinlock_t *lock)
{
    while (!spin_try_lock(lock))
        ;
}

static inline void spin_unlock(spinlock_t *lock)
{
    atomic_exchange(&lock->data, 0);
}

static inline void spin_lock_debug(spinlock_t *lock, int coreid, const char *str)
{
    while (!spin_try_lock(lock)) {
    }
}

static inline void spin_unlock_debug(spinlock_t *lock, int coreid, const char *str)
{
    atomic_exchange(&lock->data, 0);
}

#endif
